#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <cassert>
#include <vector>
#include"Task.hpp"
using namespace std;

#define PROCESS_NUM 5
int waitCommand(int waitfd,bool &quit)
{
    uint32_t command=0;
    ssize_t s= read(waitfd,&command,sizeof(command));
    if(s==0)
    {
        quit=true;
        return -1;
    }
    assert(s==sizeof(uint32_t));
    return command;
}
void sendAndWakeup(uint32_t command,pid_t who,int fd)
{
    write(fd,&command,sizeof(command));
    cout<<"主程序：call process "<<who<<" 执行 "<<desc[command]<<" 通过 "<<fd<<endl;
}
int main()
{
    Load();
    vector<pair<pid_t,int>> sloats;
    for (int i = 0; i < PROCESS_NUM; i++)
    {
        //创建管道文件
        int pipefd[2] = {0};
        int n=pipe(pipefd);
        assert(n==0);
        (void)n;
        //创建子进程
        pid_t id=fork();
        assert(id!=-1);

        if(id==0)
        {
            //子进程
            //关闭写端
            close(pipefd[1]);
            while(true)
            {
                //执行命令
                bool quit = false;
                int command = waitCommand(pipefd[0], quit); //如果对方不发，我们就阻塞
                if (quit)
                    break;
                // 执行对应的命令
                if (command >= 0 && command < HandlerSize())
                {
                    callbacks[command]();
                }
                else
                {
                    cout << "非法command: " << command << endl;
                }
            }
            exit(1);//退出子进程
        }
        //父进程
        close(pipefd[0]);//关闭读端
        sloats.push_back(make_pair(id,pipefd[1]));
    }
    //总进程派发任务
    srand((unsigned long)time(nullptr)^getpid()^13456);//产生随机数
    while(true)
    {
     //选择任务
     int command =rand()%HandlerSize();
     //选择进程执行任务
     int choice=rand()%sloats.size();   
     sendAndWakeup(command,sloats[choice].first,sloats[choice].second);
     sleep(1);
    }
    //关闭fd，所有子进程都会退出
    for(const auto& sloat :sloats)
    {
        close(sloat.second);
    }
    //收回所有的进程信息
    for(const auto & e : sloats)
    {
        waitpid(e.first,nullptr,0);
    }
}